#==================================================
#  Skill Chain （技能链）
#  链式逐个调用技能
#==================================================
# * 执行角色的技能，以顺序进行执行，上个技能的信号发出
#    后执行下个技能
# * 默认当 Skill 发出 execute_finished 或 stopped 
#    信号时，则会进行施放下一个 Skill
# * 一定要让信号连接逻辑无误，否则无法执行完列表，则就
#    一直不能执行下一个技能
# * 先调用 chain 方法进行添加响应的技能，最后调用 control
#    进行使用，例：
#	get_function("SkillChain") \
#		.chain("Attack") \
#		.chain("Sprint", Vector(200, 200)) \
#		.control()
#==================================================
# @path: res://addons/function_tree/src/custom/SkillChain.gd
# @datetime: 2021-12-16 13:22:58
#==================================================

extends "res://addons/function_tree/src/base/function/Function.gd"


signal finished(data)
signal all_finished


## 信号名称
const CONNECT_METHOD = "_next"

var __skill_node__ := {}

var _can_control : bool = true
var _list : Array = []
var _current : Dictionary
var _last : Dictionary


#==================================================
#   Set/Get
#==================================================
##  返回是否可控制（如果正在控制中，则返回 false）
func is_can_control() -> bool:
	return _can_control



#==================================================
#   自定义方法
#==================================================
#(override)
func _init_data():
	._init_data()
	register_to_function("SkillChain")


#(override)
##  开始执行
## @data 在 data 中添加字典格式的数据的格式，或数组格式的数据，或 String 字符串列表
## * 示例格式：
##control([
##	# 字典格式
##	{skill='技能名1', connect='技能信号', data=看技能是否需要进行传入数据}, 
##	# 字符串格式
##	"技能名2", "技能名3",
##	# 列表格式
##	["技能名4", '技能信号', 施放技能时传入的数据], 
##	["技能名5"], 
##	["技能名6", ['技能信号1', '技能信号2']], 
##])
##
func control(data : Array = []):
	if not is_enabled():
		return self
	
	if data.size() > 0:
		for i in data:
			if i is Array:
				if i.size() > 2: chain(i[0], i[1], i[2])
				elif i.size() > 1: chain(i[0], i[1])
				elif i.size() > 0: chain(i[0])
			elif i is Dictionary:
				if !i.has('data'):
					i['data'] = null
				if !i.has('connect'):
					i['connect'] = null
				chain(i.skill, i.data, i.connect)
			elif i is String:
				chain(i)
	
	if _can_control:
		_can_control = false
		# 翻转过来，从末尾进行弹出数据
		_list.invert()
		_next()
	return self


##  添加
## @Skill  技能名称
## @connect  连接的信号
## @data  执行时的数据
func chain(
	skill: String, 
	data = null,
	connect = null 
):
	if connect == null:
		connect = [
			"execute_finished",
			"stopped",
		]
	elif connect is String:
		connect = [connect]
	_list.push_back({
		skill = skill,
		connect = connect,
		data = data,
	})
	if !__skill_node__.has(skill):
		__skill_node__[skill] = get_skills().get_function(skill)
	return self


## 停止
func stop() -> void:
	_clear_last()
	_list.clear()
	_can_control = true


## 清除上次执行的技能数据
func _clear_last():
	if _last:
		var last_skill := __skill_node__[_last.skill] as Node
		for i in _last.connect:
			last_skill.disconnect(i, self, CONNECT_METHOD)
	_last = _current


##  下一个
func _next() -> bool:
	if _list.size() > 0:
		# 上次执行完
		_finish()
		_execute_next()
		return true
	else:
		_all_finish()
		return false


##  执行下一个
func _execute_next():
	_last = _current
	_current = _list.pop_back()
	# 执行
	var curr_skill = __skill_node__[_current.skill] as Node
	# 连接执行结束的信号
	for i in _current.connect:
		curr_skill.connect(i, self, CONNECT_METHOD)
	curr_skill.control(_current.data)
	
	# 清除上次的内容
	_clear_last()


##  执行完一次
func _finish():
	emit_signal("finished", _last)


##  所有执行完成
func _all_finish():
	_clear_last()
	_current = {}
	_can_control = true
	emit_signal("all_finished")


